package com.kuangqi.paymentdemo.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.OrderRefundInfo;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.kuangqi.paymentdemo.config.AlipayTemplate;
import com.kuangqi.paymentdemo.entity.OrderInfo;
import com.kuangqi.paymentdemo.entity.PayAsyncVo;
import com.kuangqi.paymentdemo.entity.RefundInfo;
import com.kuangqi.paymentdemo.enums.OrderStatus;
import com.kuangqi.paymentdemo.enums.alipay.TradeStatusEnums;
import com.kuangqi.paymentdemo.service.OrderInfoService;
import com.kuangqi.paymentdemo.service.RefundInfoService;
import com.kuangqi.paymentdemo.service.WeChatpayService;
import com.kuangqi.paymentdemo.util.HttpUtils;
import com.kuangqi.paymentdemo.util.WechatPay2ValidatorForRequest;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.HashMap;
import java.util.Map;

/**
 * @author kuanggong
 */

@Slf4j
@RestController
@Api(tags = "支付回调功能")
@RequestMapping("/pay")
public class OrderNotifyController {
    @Autowired
    Gson gson;
    @Autowired
    private Verifier verifier;
    @Autowired
    WeChatpayService wxPayService;
    @Autowired
    AlipayTemplate alipayTemplate;
    @Autowired
    OrderInfoService orderInfoService;
    @Autowired
    RefundInfoService refundInfoService;

    @ApiOperation("微信支付回调")
    @PostMapping("/native/notify")
    public String NativeNotify(HttpServletRequest request, HttpServletResponse response) {
        //处理通知参数
        String requestJson = HttpUtils.readData(request);

        try {
            Map<String, Object> bodyMap = gson.fromJson(requestJson, HashMap.class);
            log.info("支付通知的ID===>[{}]", bodyMap.get("id"));
            log.info("支付通知的ID===>[{}]", requestJson);
            //解析验签
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestJson, (String) bodyMap.get("id"));
            if (!wechatPay2ValidatorForRequest.validate(request)) {
                log.error("验签失败");
                response.setStatus(HttpStatus.SC_FORBIDDEN);
                Map<String, String> responseMap = new HashMap<>(2);
                responseMap.put("code", "ERROR");
                responseMap.put("message", "失败");
                return gson.toJson(responseMap);
            }
            log.info("通知验签成功");

            //处理订单
            wxPayService.processOrder(bodyMap);
            //向微信发送已收到响应
            response.setStatus(HttpStatus.SC_OK);
            Map<String, String> responseMap = new HashMap<>(2);
            responseMap.put("code", "SUCCESS");
            responseMap.put("message", "成功");
            return gson.toJson(responseMap);
        } catch (Exception e) {
            log.error("程序出现异常==>", e);
            response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
            Map<String, String> responseMap = new HashMap<>(2);
            responseMap.put("code", "FALSE");
            responseMap.put("message", "失败");
            return gson.toJson(responseMap);
        }
    }

    /**
     * 退款结果通知
     * 退款状态改变后，微信会把相关退款结果发送给商户。
     */
    @ApiOperation("微信退款结果通知")
    @PostMapping("/refunds/notify")
    public String refundsNotify(HttpServletRequest request, HttpServletResponse response) {

        log.info("退款通知执行");
        Gson gson = new Gson();
        Map<String, String> map = new HashMap<>();

        try {
            //处理通知参数
            String body = HttpUtils.readData(request);
            Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
            String requestId = (String) bodyMap.get("id");
            log.info("支付通知的id ===> {}", requestId);

            //签名的验证
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
                    = new WechatPay2ValidatorForRequest(verifier, requestId, body);
            if (!wechatPay2ValidatorForRequest.validate(request)) {

                log.error("通知验签失败");
                //失败应答
                response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
                map.put("code", "ERROR");
                map.put("message", "通知验签失败");
                return gson.toJson(map);
            }
            log.info("通知验签成功");

            //处理退款单
            wxPayService.processRefund(bodyMap);

            //成功应答
            response.setStatus(HttpStatus.SC_OK);
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            return gson.toJson(map);

        } catch (Exception e) {
            e.printStackTrace();
            //失败应答
            response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
            map.put("code", "ERROR");
            map.put("message", "失败");
            return gson.toJson(map);
        }
    }

    @ApiOperation("回调测试")
    @GetMapping("/test/notify")
    public String testNotify(HttpServletRequest request, HttpServletResponse response) {

        return "成功接收";
    }

    @ApiOperation("回调测试2")
    @GetMapping("/test/return")
    public String testReturn(HttpServletRequest request, HttpServletResponse response) {
        return "成功接收2";
    }


    @ApiOperation("支付宝电脑支付回调")
    @PostMapping("/alipay/notify")
    @SneakyThrows
    public String alipayNotify(PayAsyncVo payAsyncVo, HttpServletRequest request, HttpServletResponse response) {
        String alipay_public_key = alipayTemplate.getAlipay_public_key();
        String charset = alipayTemplate.getCharset();
        String sign_type = alipayTemplate.getSign_type();
        String s = gson.toJson(payAsyncVo);
        Map<String, String> map = gson.fromJson(s, new TypeToken<Map<String, String>>() {
        }.getType());
        boolean signVerified = AlipaySignature.rsaCheckV1(map, alipay_public_key, charset, sign_type);

        if (signVerified) {
            log.info("接收到异步通知回调验签成功,拿到的支付宝回调数据==>[{}]", payAsyncVo);
            orderInfoService.updateStatus(payAsyncVo);

            response.setStatus(HttpStatus.SC_OK);
            return "success";
        } else {
            log.error("验签失败,[{}]", payAsyncVo);
            return "false";
        }

    }

    @ApiOperation("alipay退回银行卡通知回调")
    @GetMapping("/alipay/bankcard/notify")
    @SneakyThrows
    public String alipayBankCardNotify(@RequestBody Map<String, String> paramMap) {
        try {
            String alipay_public_key = alipayTemplate.getAlipay_public_key();
            String charset = alipayTemplate.getCharset();
            String sign_type = alipayTemplate.getSign_type();

            boolean signVerified = AlipaySignature.rsaCheckV1(paramMap, alipay_public_key, charset, sign_type);
            if (signVerified) {
                refundInfoService.update(new UpdateWrapper<RefundInfo>().eq("order_no",paramMap.get("out_trade_no")).set("refund_root",paramMap.get("dback_status")));
            }
            return "success";
        } catch (AlipayApiException e) {
            log.error("程序出现问题===>[{}]",e);
            return "false";
        }
    }

}
